| id | time | y | x1 | x2 |
|---|---|---|---|---|
| 1 | 1 | 0 | 0 | 20 |
| 1 | 2 | 0 | 0 | 21 |
| 1 | 3 | 6 | 1 | 26 |
| 2 | 1 | 5 | 1 | 34 |
| 2 | 2 | 6 | 1 | 36 |
| 2 | 3 | 7 | 1 | 42 |
| 3 | 1 | 12 | 1 | 44 |
| 3 | 2 | 9 | 0 | 30 |
| 3 | 3 | 9 | 0 | 40 |
Week 6: Panel models
University of Oxford
Panel models - what and why
Fixed effects model
Random effects model
Interactions
Dynamic panel models with FE/RE within SEM
Extensions
We want to relate changes in X to changes in Y within individuals
For example:
how is a change in employment associated with a change in voting behaviour?
how are changes in income associated with changes in health?
how is a change in parental status associated with changes in employment?
By looking at within individual change, we control for all time-constant variables, observed or unobserved
We usually work with individuals (\(i\)) observed over time (\(t\)), but that is just a specific case of observations nested with some group
Cases (N) over time (T)
Cases are independent, but observations (T) within a case are correlated
Balanced: all cases have equal T
Unbalanced: T varies from case to case
Regular time intervals
Examples:
time-varying
\(x_{it}\) varies between individuals \(i\) and within individuals across time \(t\)
outcome \(Y_{it}\) also varies between and within cases
time-constant (time-invariant)
\(x_{i.}\) has the same value across \(t\)
this includes fixed characteristics like sex at birth or country of origin
constant in principle vs constant in the data
individual-constant (invariant)
\(x_{.t}\) is the same for all individuals but varies across time
like a level-2 variable in multilevel models, a supra-individual quantity (weather, GDP)
Some continuous outcome \(y_{it}\)
Grand mean is \(\bar{y}\)
Mean for individual \(i\) is \(\bar{y}_i\)
Total variance \(\sum{(y_{it} - \bar{y})^2}\)
Within variance \(\sum{(y_{it} - \bar{y_i})^2}\)
Between variance \(\sum{(\bar{y_i} - \bar{y})^2}\)
This video has a great visualization of between and within variation in FE models (between minutes 6 and 9)
| id | time | y | x1 | x2 |
|---|---|---|---|---|
| 1 | 1 | 0 | 0 | 20 |
| 1 | 2 | 0 | 0 | 21 |
| 1 | 3 | 6 | 1 | 26 |
| 2 | 1 | 5 | 1 | 34 |
| 2 | 2 | 6 | 1 | 36 |
| 2 | 3 | 7 | 1 | 42 |
| 3 | 1 | 12 | 1 | 44 |
| 3 | 2 | 9 | 0 | 30 |
| 3 | 3 | 9 | 0 | 40 |
N=3, T=3, balanced,
\(y\) is a continuous outcome, \(x1\) binary, \(x2\) continuous
| id | time | y | y_gmean | y_imean | y_tot | y_betw | y_with |
|---|---|---|---|---|---|---|---|
| 1 | 1 | 0 | 6 | 2 | -6 | -4 | -2 |
| 1 | 2 | 0 | 6 | 2 | -6 | -4 | -2 |
| 1 | 3 | 6 | 6 | 2 | 0 | -4 | 4 |
| 2 | 1 | 5 | 6 | 6 | -1 | 0 | -1 |
| 2 | 2 | 6 | 6 | 6 | 0 | 0 | 0 |
| 2 | 3 | 7 | 6 | 6 | 1 | 0 | 1 |
| 3 | 1 | 12 | 6 | 10 | 6 | 4 | 2 |
| 3 | 2 | 9 | 6 | 10 | 3 | 4 | -1 |
| 3 | 3 | 9 | 6 | 10 | 3 | 4 | -1 |
| id | time | x1 | x1_gmean | x1_imean | x1_betw | x1_with |
|---|---|---|---|---|---|---|
| 1 | 1 | 0 | 0.556 | 0.333 | -0.222 | -0.333 |
| 1 | 2 | 0 | 0.556 | 0.333 | -0.222 | -0.333 |
| 1 | 3 | 1 | 0.556 | 0.333 | -0.222 | 0.667 |
| 2 | 1 | 1 | 0.556 | 1.000 | 0.444 | 0.000 |
| 2 | 2 | 1 | 0.556 | 1.000 | 0.444 | 0.000 |
| 2 | 3 | 1 | 0.556 | 1.000 | 0.444 | 0.000 |
| 3 | 1 | 1 | 0.556 | 0.333 | -0.222 | 0.667 |
| 3 | 2 | 0 | 0.556 | 0.333 | -0.222 | -0.333 |
| 3 | 3 | 0 | 0.556 | 0.333 | -0.222 | -0.333 |
| id | time | x2 | x2_gmean | x2_imean | x2_betw | x2_with |
|---|---|---|---|---|---|---|
| 1 | 1 | 20 | 32.6 | 22.3 | -10.22 | -2.33 |
| 1 | 2 | 21 | 32.6 | 22.3 | -10.22 | -1.33 |
| 1 | 3 | 26 | 32.6 | 22.3 | -10.22 | 3.67 |
| 2 | 1 | 34 | 32.6 | 37.3 | 4.78 | -3.33 |
| 2 | 2 | 36 | 32.6 | 37.3 | 4.78 | -1.33 |
| 2 | 3 | 42 | 32.6 | 37.3 | 4.78 | 4.67 |
| 3 | 1 | 44 | 32.6 | 38.0 | 5.44 | 6.00 |
| 3 | 2 | 30 | 32.6 | 38.0 | 5.44 | -8.00 |
| 3 | 3 | 40 | 32.6 | 38.0 | 5.44 | 2.00 |
| id | time | y | x1 | y_with | x1_with | x2_with |
|---|---|---|---|---|---|---|
| 1 | 1 | 0 | 0 | -2 | -0.333 | -2.33 |
| 1 | 2 | 0 | 0 | -2 | -0.333 | -1.33 |
| 1 | 3 | 6 | 1 | 4 | 0.667 | 3.67 |
| 2 | 1 | 5 | 1 | -1 | 0.000 | -3.33 |
| 2 | 2 | 6 | 1 | 0 | 0.000 | -1.33 |
| 2 | 3 | 7 | 1 | 1 | 0.000 | 4.67 |
| 3 | 1 | 12 | 1 | 2 | 0.667 | 6.00 |
| 3 | 2 | 9 | 0 | -1 | -0.333 | -8.00 |
| 3 | 3 | 9 | 0 | -1 | -0.333 | 2.00 |
| id | time | y | x1 | y_with | x1_with | x2_with | sexatb | sexatb_with |
|---|---|---|---|---|---|---|---|---|
| 1 | 1 | 0 | 0 | -2 | -0.333 | -2.33 | 0 | 0 |
| 1 | 2 | 0 | 0 | -2 | -0.333 | -1.33 | 0 | 0 |
| 1 | 3 | 6 | 1 | 4 | 0.667 | 3.67 | 0 | 0 |
| 2 | 1 | 5 | 1 | -1 | 0.000 | -3.33 | 1 | 0 |
| 2 | 2 | 6 | 1 | 0 | 0.000 | -1.33 | 1 | 0 |
| 2 | 3 | 7 | 1 | 1 | 0.000 | 4.67 | 1 | 0 |
| 3 | 1 | 12 | 1 | 2 | 0.667 | 6.00 | 1 | 0 |
| 3 | 2 | 9 | 0 | -1 | -0.333 | -8.00 | 1 | 0 |
| 3 | 3 | 9 | 0 | -1 | -0.333 | 2.00 | 1 | 0 |
No variation in time-constant x
Therefore: can’t explain within-variation in y
This video sells the fixest package very well and shows off some of its options
plm has handy functions for data inspection and has random effect models
# A tibble: 2 × 5
term estimate std.error statistic p.value
<chr> <dbl> <dbl> <dbl> <dbl>
1 (Intercept) 2.74e-16 0.282 9.74e-16 1.000
2 x1_with 4.5 e+ 0 0.732 6.15e+ 0 0.000468
OLS estimation, Dep. Var.: y
Observations: 9
Fixed-effects: id: 3
Standard-errors: IID
Estimate Std. Error t value Pr(>|t|)
x1 4.5 0.866 5.2 0.0034782 **
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
RMSE: 0.745356 Adj. R2: 0.9375
Within R2: 0.84375
Oneway (individual) effect Within Model
Call:
plm(formula = y ~ x1, data = df, model = "within", index = c("id"))
Balanced Panel: n = 3, T = 3, N = 9
Residuals:
1 2 3 4 5 6 7 8 9
-0.5 -0.5 1.0 -1.0 0.0 1.0 -1.0 0.5 0.5
Coefficients:
Estimate Std. Error t-value Pr(>|t|)
x1 4.500 0.866 5.2 0.0035 **
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Total Sum of Squares: 32
Residual Sum of Squares: 5
R-Squared: 0.844
Adj. R-Squared: 0.75
F-statistic: 27 on 1 and 5 DF, p-value: 0.00348
Oneway (individual) effect First-Difference Model
Call:
plm(formula = y ~ x1, data = df, model = "fd", index = c("id"))
Balanced Panel: n = 3, T = 3, N = 9
Observations used in estimation: 6
Residuals:
2 3 5 6 8 9
-0.833 0.667 0.167 0.167 0.667 -0.833
attr(,"na.action")
1 4 7
1 4 7
attr(,"class")
[1] "omit"
Coefficients:
Estimate Std. Error t-value Pr(>|t|)
(Intercept) 0.833 0.312 2.67 0.0557 .
x1 4.500 0.540 8.33 0.0011 **
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Total Sum of Squares: 42.8
Residual Sum of Squares: 2.33
R-Squared: 0.946
Adj. R-Squared: 0.932
F-statistic: 69.4286 on 1 and 4 DF, p-value: 0.00113
# A tibble: 3 × 5
term estimate std.error statistic p.value
<chr> <dbl> <dbl> <dbl> <dbl>
1 (Intercept) 2.74e-16 0.282 9.74e-16 1.000
2 x1_with 4.5 e+ 0 0.732 6.15e+ 0 0.000468
3 sexatb_with NA NA NA NA
OLS estimation, Dep. Var.: y
Observations: 9
Fixed-effects: id: 3
Standard-errors: IID
Estimate Std. Error t value Pr(>|t|)
x1 4.5 0.866 5.2 0.0034782 **
... 1 variable was removed because of collinearity (sexatb)
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
RMSE: 0.745356 Adj. R2: 0.9375
Within R2: 0.84375
| id | time | y | x1 | y_with | x1_with |
|---|---|---|---|---|---|
| 1 | 1 | 0 | 0 | -2 | -0.333 |
| 1 | 2 | 0 | 0 | -2 | -0.333 |
| 1 | 3 | 6 | 1 | 4 | 0.667 |
| 2 | 1 | 5 | 1 | -1 | 0.000 |
| 2 | 2 | 6 | 1 | 0 | 0.000 |
| 2 | 3 | 7 | 1 | 1 | 0.000 |
| 3 | 1 | 12 | 1 | 2 | 0.667 |
| 3 | 2 | 9 | 0 | -1 | -0.333 |
| 3 | 3 | 9 | 0 | -1 | -0.333 |
Coefficient of 4.5 is identified by cases 1 and 3
One up \(\Delta\) 6 and one down \(\Delta\)-3 make for 9/2=4.5
| id | time | y | x1 |
|---|---|---|---|
| 1 | 1 | 0 | 0 |
| 1 | 2 | 0 | 0 |
| 1 | 3 | 6 | 1 |
| 2 | 1 | 5 | 1 |
| 2 | 2 | 6 | 1 |
| 2 | 3 | 7 | 1 |
| 3 | 1 | 12 | 1 |
| 3 | 2 | 9 | 1 |
| 3 | 3 | 9 | 1 |
What do you think the coefficient will be?
OLS estimation, Dep. Var.: y
Observations: 9
Fixed-effects: id: 3
Standard-errors: IID
Estimate Std. Error t value Pr(>|t|)
x1 6 1.55 3.87 0.011725 *
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
RMSE: 0.942809 Adj. R2: 0.9
Within R2: 0.75
| id | time | y | x1 |
|---|---|---|---|
| 1 | 1 | 0 | 0 |
| 1 | 2 | 0 | 0 |
| 1 | 3 | 6 | 1 |
| 2 | 1 | 5 | 1 |
| 2 | 2 | 6 | 1 |
| 2 | 3 | 7 | 1 |
| 3 | 1 | 12 | 1 |
| 3 | 2 | 9 | 1 |
| 3 | 3 | 9 | 0 |
OLS estimation, Dep. Var.: y
Observations: 9
Fixed-effects: id: 3
Standard-errors: IID
Estimate Std. Error t value Pr(>|t|)
x1 3.75 1.41 2.66 0.044885 *
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
RMSE: 1.21335 Adj. R2: 0.834375
Within R2: 0.585938
Why 3.75?
Case 1: average Y was 0 when x=0 and 6 when x=1, a difference of 6
Case 3: average Y was 9 when x=0 and 10.5 when x=1, a difference of 1.5
| id | time | y | x1 |
|---|---|---|---|
| 1 | 1 | 0 | 0 |
| 1 | 2 | 0 | 1 |
| 1 | 3 | 6 | 1 |
| 2 | 1 | 5 | 1 |
| 2 | 2 | 6 | 1 |
| 2 | 3 | 7 | 1 |
| 3 | 1 | 12 | 1 |
| 3 | 2 | 9 | 1 |
| 3 | 3 | 9 | 0 |
OLS estimation, Dep. Var.: y
Observations: 9
Fixed-effects: id: 3
Standard-errors: IID
Estimate Std. Error t value Pr(>|t|)
x1 2.25 1.95 1.16 0.29987
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
RMSE: 1.67498 Adj. R2: 0.684375
Within R2: 0.210938
Why 2.25?
Case 1: average Y was 3 when x=0 and 6 when x=1, a difference of 3
Case 3: average Y was 9 when x=0 and 10.5 when x=1, a difference of 1.5
Two-way Fixed effects model (TWFE)
Two fixed effects: individual \(i\) and time \(t\)
Our model now looks like this:
\[y_{it} = \beta x_{it} + \alpha_i + \zeta_t + \epsilon_{it}\] time fixed-effects \(\zeta_t\)
indiviudal fixed-effects \(\alpha_i\)
In demeaned form TWFE looks like this:
\[(y_{it} - \bar{y_i} - \bar{y_t} + \bar{y}) = \beta (x_{it} - \bar{x_i} - \bar{x_t} + \bar{x}) + (\epsilon_{it} - \epsilon_i - \epsilon_t + \epsilon)\]
TWFE takes into account information about time trends from those without changes in x
TWFE introduces two new assumptions in DiD:
(see Rüttenauer & Aksoy 2024 for guidance on this)
In OLS our errors should be IID: independent and identically distributed
When we have panel data, it is likely that IID doesn’t hold and that our errors are:
autocorrelated: error at t1 is correlated witherror at t2, etc
heteroskedastic: variance is not constant
The normal standard errors, which we would get if we use lm, are not ‘correct’. We are underestimating our se. In panel models it is better to use clustered se that allow for some correlation between errors within individuals.
Works better when you have more clusters, preferable > 50
(for when and which groups to clsuer on, see this paper)
robust standard errors = heteroskadisticy consistent errors, give more weight when residual variance is large
(probably used too often, see Gary King video here)
Enough variance in X?
Effect of going up or down?
Always:
Articulate your theory
Look at your data and provide descriptive statistics
Think hard about what difference you are identifying and which SE you use
Can not estimate between-differences; no effects of ethnicity, country of origin, etc
If there is very little within variation in a characteristic, that variation can be drowned out by the fixed effects
Coefficients are heavily influenced by cases with a lot of variation on X
Coefficients are weighted averages of ups and downs
| id | time | y | x1 | x2 | y_betw | x1_betw | x2_betw |
|---|---|---|---|---|---|---|---|
| 1 | 1 | 0 | 0 | 20 | -4 | -0.222 | -10.22 |
| 1 | 2 | 0 | 0 | 21 | -4 | -0.222 | -10.22 |
| 1 | 3 | 6 | 1 | 26 | -4 | -0.222 | -10.22 |
| 2 | 1 | 5 | 1 | 34 | 0 | 0.444 | 4.78 |
| 2 | 2 | 6 | 1 | 36 | 0 | 0.444 | 4.78 |
| 2 | 3 | 7 | 1 | 42 | 0 | 0.444 | 4.78 |
| 3 | 1 | 12 | 1 | 44 | 4 | -0.222 | 5.44 |
| 3 | 2 | 9 | 0 | 30 | 4 | -0.222 | 5.44 |
| 3 | 3 | 9 | 0 | 40 | 4 | -0.222 | 5.44 |
Oneway (individual) effect Between Model
Call:
plm(formula = y ~ x1, data = df, model = "between", index = c("id"))
Balanced Panel: n = 3, T = 3, N = 9
Observations used in estimation: 3
Residuals:
1 2 3
-4.00e+00 6.66e-16 4.00e+00
Coefficients:
Estimate Std. Error t-value Pr(>|t|)
(Intercept) 6.00e+00 6.63e+00 0.9 0.53
x1 -4.26e-15 1.04e+01 0.0 1.00
Total Sum of Squares: 32
Residual Sum of Squares: 32
R-Squared: 0
Adj. R-Squared: -1
F-statistic: 1.68371e-31 on 1 and 1 DF, p-value: 1
# A tibble: 2 × 5
term estimate std.error statistic p.value
<chr> <dbl> <dbl> <dbl> <dbl>
1 (Intercept) -4.86 3.97 -1.23 0.220
2 x2 0.334 0.114 2.94 0.00333
weighted combination of within and between coefficient!
# A tibble: 4 × 6
effect group term estimate std.error statistic
<chr> <chr> <chr> <dbl> <dbl> <dbl>
1 fixed <NA> (Intercept) -5.56 3.13 -1.77
2 fixed <NA> x2 0.355 0.0922 3.85
3 ran_pars id sd__(Intercept) 1.20 NA NA
4 ran_pars Residual sd__Observation 1.73 NA NA
mwb <- lmer(y ~ 1 + x2_with + x2_imean + (1 | id), data = df, REML = FALSE)
tidy(mwb) # within and between effects, var components unchanged# A tibble: 5 × 6
effect group term estimate std.error statistic
<chr> <chr> <chr> <dbl> <dbl> <dbl>
1 fixed <NA> (Intercept) -7.00 4.06 -1.72
2 fixed <NA> x2_with 0.301 0.135 2.22
3 fixed <NA> x2_imean 0.399 0.122 3.28
4 ran_pars id sd__(Intercept) 1.16 NA NA
5 ran_pars Residual sd__Observation 1.71 NA NA
RE models takes within and between variance into account
Compare the between and within coefficients in the previous slides
Continuous outcome \(Y\) for individual \(i\) at time points \(j\)
\[Y_{ij} = \beta_{0j} + \beta_{1j}x_{ij} + ... + R_{ij}\]
intercepts can vary by individual:
\[\beta_{0j} = \gamma_{00} + U_{0j}\]
keep coefficients (slopes) constant!
Within individual residuals \(R_{ij}\) have variance \(\sigma^2\)
Between individual residuals have variance: \(var(U_{0j}) = \tau_{00} = \tau_0^2\)
Compares FE and RE
If estates are close, RE is preferred
Better to be led by theory (see here in The Effect)
DWH compares FE to basic RE model, other RE models are available
| ID | YEAR | gender | income | nchildren | |
|---|---|---|---|---|---|
| 2.1984 | 2 | 1984 | 2 | 31500 | 0 |
| 2.1986 | 2 | 1986 | 2 | 40000 | 0 |
| 2.1988 | 2 | 1988 | 2 | 20000 | 0 |
| 2.1990 | 2 | 1990 | 2 | 20100 | 0 |
| 2.1992 | 2 | 1992 | 2 | NA | 0 |
| 2.1994 | 2 | 1994 | 2 | NA | 1 |
| 2.1996 | 2 | 1996 | 2 | NA | 2 |
| 2.1998 | 2 | 1998 | 2 | 51000 | 2 |
| 2.2000 | 2 | 2000 | 2 | 45000 | 2 |
| 2.2002 | 2 | 2002 | 2 | 50450 | 2 |
OLS estimation, Dep. Var.: income
Observations: 975
Fixed-effects: ID: 95
Standard-errors: IID
Estimate Std. Error t value Pr(>|t|)
nchildren 25811 3493 7.39 3.4073e-13 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
RMSE: 84,855.3 Adj. R2: 0.288889
Within R2: 0.058501
# A tibble: 1 × 5
term estimate std.error statistic p.value
<chr> <dbl> <dbl> <dbl> <dbl>
1 nchildren 25811. 3493. 7.39 3.41e-13
plm comes in handy here to inspect and check the data structure
sample$nchildrenXfemale <- sample$nchildren*sample$female
fe_i <- feols(income ~ nchildren + female + nchildrenXfemale | ID, sample)
summary(fe_i)OLS estimation, Dep. Var.: income
Observations: 975
Fixed-effects: ID: 95
Standard-errors: IID
Estimate Std. Error t value Pr(>|t|)
nchildren 23192 6834 3.394 0.00072029 ***
nchildrenXfemale 3545 7952 0.446 0.65580799
... 1 variable was removed because of collinearity (female)
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
RMSE: 84,845.7 Adj. R2: 0.28824
Within R2: 0.058714
# A tibble: 6 × 5
# Groups: id [2]
id z t xit yit
<dbl> <dbl> <int> <dbl> <dbl>
1 1 -2.41 1 -3.88 -3.68
2 1 -2.41 2 -2.13 -3.43
3 1 -2.41 3 -2.15 -5.13
4 1 -2.41 4 0.455 -1.96
5 2 0.555 1 -2.84 -1.25
6 2 0.555 2 -1.62 0.174
modelsummary::msummary(list(lm_t, lm_f, fe), stars = TRUE,
gof_map = c("nobs", "r.squared", "bic") )| (1) | (2) | (3) | |
|---|---|---|---|
| + p < 0.1, * p < 0.05, ** p < 0.01, *** p < 0.001 | |||
| (Intercept) | 0.022 | -0.027 | |
| (0.031) | (0.041) | ||
| xit | 0.416*** | 0.636*** | 0.418*** |
| (0.014) | (0.018) | (0.018) | |
| z | 0.872*** | ||
| (0.016) | |||
| Num.Obs. | 4000 | 4000 | 4000 |
| R2 | 0.560 | 0.248 | 0.146 |
| BIC | 16816.4 | 18955.2 | 15677.8 |
# A tibble: 6 × 10
# Groups: id [6]
id z xit_1 xit_2 xit_3 xit_4 yit_1 yit_2 yit_3 yit_4
<dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 1 -2.41 -3.88 -2.13 -2.15 0.455 -3.68 -3.43 -5.13 -1.96
2 2 0.555 -2.84 -1.62 -3.01 1.49 -1.25 0.174 -1.74 1.88
3 3 2.17 -1.78 -4.57 -2.53 -2.88 5.10 -0.0327 3.49 0.550
4 4 -4.69 -0.177 0.343 -3.32 1.28 -4.96 -7.31 -8.05 -0.255
5 5 0.858 1.89 1.43 1.49 1.83 6.13 0.561 0.729 -1.09
6 6 1.01 0.344 -2.66 -1.51 3.99 2.73 -0.0258 -0.436 -0.129
lavaan
library(lavaan)
mod <- 'yit_1 ~ b*xit_1
yit_2 ~ b*xit_2
yit_3 ~ b*xit_3
yit_4 ~ b*xit_4
A =~ 1*yit_1 + 1*yit_2 + 1*yit_3 + 1*yit_4
yit_1 + yit_2 + yit_3 + yit_4 ~ a*1
yit_1 ~~ e*yit_1
yit_2 ~~ e*yit_2
yit_3 ~~ e*yit_3
yit_4 ~~ e*yit_4
xit_1 ~~ NA*A
xit_2 ~~ NA*A
xit_3 ~~ NA*A
xit_4 ~~ NA*A'
fesem <- sem(mod, data = dw)lavaan
lavaan 0.6-21 ended normally after 41 iterations
Estimator ML
Optimization method NLMINB
Number of model parameters 25
Number of equality constraints 9
Number of observations 1000
Model Test User Model:
Test statistic 453.934
Degrees of freedom 28
P-value (Chi-square) 0.000
Parameter Estimates:
Standard errors Standard
Information Expected
Information saturated (h1) model Structured
Latent Variables:
Estimate Std.Err z-value P(>|z|)
A =~
yit_1 1.000
yit_2 1.000
yit_3 1.000
yit_4 1.000
Regressions:
Estimate Std.Err z-value P(>|z|)
yit_1 ~
xit_1 (b) 0.418 0.016 26.929 0.000
yit_2 ~
xit_2 (b) 0.418 0.016 26.929 0.000
yit_3 ~
xit_3 (b) 0.418 0.016 26.929 0.000
yit_4 ~
xit_4 (b) 0.418 0.016 26.929 0.000
Covariances:
Estimate Std.Err z-value P(>|z|)
A ~~
xit_1 0.817 0.145 5.631 0.000
xit_2 0.559 0.136 4.098 0.000
xit_3 0.560 0.138 4.051 0.000
xit_4 0.574 0.143 4.023 0.000
Intercepts:
Estimate Std.Err z-value P(>|z|)
.yit_1 (a) -0.024 0.061 -0.400 0.689
.yit_2 (a) -0.024 0.061 -0.400 0.689
.yit_3 (a) -0.024 0.061 -0.400 0.689
.yit_4 (a) -0.024 0.061 -0.400 0.689
xit_1 0.090 0.075 1.207 0.228
xit_2 -0.001 0.072 -0.008 0.994
xit_3 -0.055 0.073 -0.755 0.450
xit_4 0.011 0.075 0.144 0.885
Variances:
Estimate Std.Err z-value P(>|z|)
.yit_1 (e) 3.916 0.101 38.730 0.000
.yit_2 (e) 3.916 0.101 38.730 0.000
.yit_3 (e) 3.916 0.101 38.730 0.000
.yit_4 (e) 3.916 0.101 38.730 0.000
xit_1 5.626 0.252 22.361 0.000
xit_2 5.149 0.230 22.361 0.000
xit_3 5.290 0.237 22.361 0.000
xit_4 5.628 0.252 22.361 0.000
A 2.738 0.169 16.211 0.000
Econ lit: GMM—problematic
ML-SEM: easy, works with all SEM packages, all advantages of doing FE in SEM
FE-DPM
Less flexible than Allison et al. (2017)
Otherwise very similar
Suitable if attention is on x \(\rightarrow\) y
But error correlations in Allison et al. makes it more flexible
RI-CLPM
Suitable when x and y have stable individual component (psyc construct)
Focus is on temporal deviations from stable component
Do not block “backdoors” via FE
Less “causal” leverage
First differences, between effects, see an example here with interactions (!)
Different types of outcomes: Logit, ordered, multinomial, poisson
Many flavours of standard errors
Combining it with Instrumental Variables
Fixed Effects Individual Slopes (FEIS)
DiD (incl TWFE) models
Present DiD/TWFE as a event study, fect package